<template>
  <div class="container">
    <div class="app-container">
      <!-- 添加角色按钮 -->
      <div class="add-role-btn">
        <el-button type="primary" size="mini" @click="showDialog = true"
          >添加角色</el-button
        >
      </div>
      <!-- 表格 -->
      <el-table :data="list">
        <el-table-column label="角色" align="center" width="200" prop="name">
          <template #default="{ row }">
            <el-input
              v-if="row.isEdit"
              v-model="row.editRow.name"
              size="mini"
            ></el-input>
            <span v-else>{{ row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column label="启用" align="center" width="200" prop="state">
          <template #default="{ row }">
            <el-switch
              v-if="row.isEdit"
              v-model="row.editRow.state"
              :active-value="1"
              :inactive-value="0"
            ></el-switch>
            <span v-else>{{ row.state === 1 ? "启用" : "未启用" }}</span>
          </template>
        </el-table-column>
        <el-table-column label="描述" align="center" prop="description">
          <template #default="{ row }">
            <el-input
              v-if="row.isEdit"
              v-model="row.editRow.description"
              type="textarea"
            ></el-input>
            <span v-else>{{ row.description }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center">
          <template #default="{ row }">
            <template v-if="row.isEdit">
              <el-button type="primary" size="mini" @click="editBtnOK(row)"
                >确定</el-button
              >
              <el-button size="mini" @click="row.isEdit = false">
                取消
              </el-button>
            </template>
            <template v-else>
              <el-button
                type="text"
                size="mini"
                @click="showPermissionDialog(row.id)"
                >分配权限</el-button
              >
              <el-button type="text" size="mini" @click="edit(row)">
                编辑
              </el-button>
              <!-- 气泡确认框 -->
              <el-popconfirm
                title="这是一段内容确定删除吗？"
                @onConfirm="popConfirm(row)"
              >
                <template #reference>
                  <el-button style="margin-left: 10px" type="text" size="mini"
                    >删除</el-button
                  >
                </template>
              </el-popconfirm>
            </template>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <el-row type="flex" justify="end" align="middle" style="height: 60px">
        <el-pagination
          :current-page="params.page"
          :page-size="params.pagesize"
          :total="total"
          layout="prev,pager,next"
          @current-change="handleCurrentChange"
        ></el-pagination>
      </el-row>
    </div>
    <!-- 添加/编辑弹窗 -->
    <el-dialog title="添加角色" :visible="showDialog" @close="closeDialog">
      <!-- 表单内容 -->
      <el-form
        ref="roleRef"
        label-width="80px"
        :model="roleForm"
        :rules="roleRules"
      >
        <el-form-item label="角色名称" prop="name">
          <el-input
            v-model="roleForm.name"
            size="mini"
            style="width: 80%"
          ></el-input>
        </el-form-item>
        <!-- prop： -->
        <!-- 1. 指定表单校验的字段 -->
        <!-- 2. resetFields重置表单的方法，只能清空绑定了prop的表单项 -->
        <el-form-item label="启用" prop="state">
          <el-switch v-model="roleForm.state" size="mini"></el-switch>
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input
            v-model="roleForm.description"
            type="textarea"
            :rows="3"
            size="mini"
            style="width: 80%"
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-row type="flex" justify="center">
            <el-col :span="12">
              <el-button type="primary" size="mini" @click="btnOK"
                >确定</el-button
              >
              <el-button size="mini" @click="closeDialog">取消</el-button>
            </el-col>
          </el-row>
        </el-form-item> </el-form
      >·
    </el-dialog>
    <!-- 给角色分配权限弹窗 -->
    <!-- check-strictly：取消节点之间的父子关联 -->
    <el-dialog title="分配权限" :visible.sync="permissionVisible">
      <!-- 所有的权限数据对应的树形结构 -->
      <el-tree
        ref="permTreeRef"
        :data="permissionList"
        :props="{ label: 'name' }"
        default-expand-all
        show-checkbox
        :default-checked-keys="permIds"
        node-key="id"
        check-strictly
      ></el-tree>
      <!-- 确定取消按钮 -->
      <div style="text-align: center; margin-top: 40px">
        <el-button type="primary" size="mini" @click="assignPermission"
          >确定</el-button
        >
        <el-button size="mini" @click="permissionVisible = false"
          >取消</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  addRole,
  assignPermission,
  delRole,
  editRole,
  getRoleDetail,
  getRoleList,
} from "@/api/role";
import { getPermissionList } from "@/api/permission";
import { listToTree } from "@/utils";

export default {
  // 组件name属性，给组件起一个名字
  // 作用：帮助我们在vue的调试工具中，快速找到该组件
  name: "Role",
  data() {
    return {
      // 表格列表数据
      list: [],
      // 分页请求参数
      params: {
        page: 1,
        pagesize: 5,
      },
      // 总条数
      total: 0,
      // 控制弹窗显示隐藏的布尔值
      showDialog: false,
      // 表单数据对象
      roleForm: {
        name: "",
        state: 0,
        description: "",
      },
      // 表单校验规则对象
      roleRules: {
        name: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
        description: [
          { required: true, message: "请输入角色描述", trigger: "blur" },
        ],
      },
      // 控制给角色分配权限弹窗的显示与隐藏
      permissionVisible: false,
      // 所有权限的树形结构数据
      permissionList: [],
      // 选中的权限id组成的数组
      permIds: [],
      // 当前角色id
      currentId: "",
    };
  },
  created() {
    this.getRoleList();
  },
  methods: {
    // 获取角色列表数据
    async getRoleList() {
      const res = await getRoleList(this.params);
      this.list = res.data.rows;

      this.list.forEach((item) => {
        // 为表格数据中的每一行数据添加一个isEdit字段，isEdit字段用于控制某行表格是否处于编辑状态
        // vue2里数据会丢失响应式的情况
        // 情况1：给对象添加新的属性时，这个新的属性对应的数据是没有响应式的。
        // 情况2：给数组使用下标添加新的数组元素时，新添加的数组元素对应的数据没有响应式
        // item.isEdit = false;
        // this.$set() 让数据保持响应式
        // this.$set(对象, 新添加的属性, 新添加的属性值)
        this.$set(item, "isEdit", false);
        // 为表格数据中的每一行数据添加一个editRow字段，作为缓存数据，将来表单双向绑定该缓存数据
        this.$set(item, "editRow", {
          name: item.name,
          state: item.state,
          description: item.description,
        });
        console.log(this.list);
      });
      // console.log(this.list);
      this.total = res.data.total;
    },
    // 当前页码发生变化触发的回调函数
    handleCurrentChange(page) {
      // page：当前最新的页码值
      // console.log("页码值发生变化", page);
      // 将当前最新的页码值赋值给请求参数中的页码值字段
      this.params.page = page;
      // 使用最新的页码值发送请求，回去对应的表格数据
      this.getRoleList();
    },
    // 点击X和蒙板时会触发的回调函数
    closeDialog() {
      // 关闭弹窗
      this.showDialog = false;
      // 清空表单
      this.$refs.roleRef.resetFields();
    },
    // 点击确定
    btnOK() {
      // 兜底校验
      this.$refs.roleRef.validate(async (isOK) => {
        if (isOK) {
          // 校验通过
          // 发起添加角色的接口请求
          await addRole(this.roleForm);
          // 提示用户
          this.$message.success("添加成功");
          // 刷新列表数据
          this.getRoleList();
          // 重置表单、关闭弹窗
          this.closeDialog();
        }
      });
    },
    // 点击编辑
    edit(row) {
      // row 表格中的一行数据
      // console.log(row);
      // 进入编辑状态
      row.isEdit = true;
      // 将表格的数据赋值给缓存数据
      row.editRow.name = row.name;
      row.editRow.state = row.state;
      row.editRow.description = row.description;
    },
    // 点击编辑状态中的确定按钮
    async editBtnOK(row) {
      // 校验是否必填
      if (row.editRow.name && row.editRow.description) {
        // 校验通过
        // 调用编辑角色接口
        await editRole({
          ...row.editRow,
          id: row.id,
        });
        // 提示用户i
        this.$message.success("编辑成功");
        // 更新表格数据
        // 将缓存数据赋值给表格数据
        row.name = row.editRow.name;
        row.state = row.editRow.state;
        row.description = row.editRow.description;
        // 退出编辑
        row.isEdit = false;
      } else {
        // 校验不通过
        this.$message.warning("角色名称和角色描述不能为空");
      }
    },
    // 点击气泡确认框的确定按钮
    async popConfirm(row) {
      // 调用删除角色接口
      await delRole(row.id);
      // 提示用户
      this.$message.success("删除成功");
      // 处理分页
      // 当前页只有一条数据 并且 当前页是大于一 时
      if (this.list.length === 1 && this.params.page > 1) {
        // 页数减一
        this.params.page--;
      }
      // 刷新列表
      this.getRoleList();
    },
    // 点击分配角色按钮
    async showPermissionDialog(id) {
      // id: 角色id
      this.currentId = id;
      // 调用获取权限列表数据的接口
      const res = await getPermissionList();
      this.permissionList = listToTree(res.data, 0);
      // 调用获取该角色已有的权限数据接口
      const result = await getRoleDetail(id);
      this.permIds = result.data.permIds;
      // 打开给角色分配权限的弹窗
      this.permissionVisible = true;
    },
    // 点击给角色分配权限的确定按钮
    async assignPermission() {
      console.log(this.$refs.permTreeRef.getCheckedKeys());
      // 调用给角色分配权限接口
      await assignPermission({
        id: this.currentId, // 角色id
        permIds: this.$refs.permTreeRef.getCheckedKeys(), // 用户选中的权限id组成的数组
      });
      // 提示用户
      this.$message.success("分配权限成功");
      // 关闭弹窗
      this.permissionVisible = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.add-role-btn {
  padding: 10px;
}
</style>
